<?php

namespace shisou\tpgii\handler;

use think\helper\Str;

class Model
{
    private $tables;

    public function __construct(array $tables)
    {
        $this->tables = $tables;
    }

    public function run()
    {
        $tables = $this->tables;

        $this->createARModel();

        foreach ($tables as $table) {
            $name   = '$table';
            $schema = '$schema';
            // 所有字段
            $cols = $table['cols'];
            // 类名
            $className     = Str::studly($table['tableName']);
            $baseClassName = '\app\model\AR';

            // 文件名
            $modelFile = root_path() . "/app/model/{$className}.php";

            // ---------- 自定义代码 ----------

            $parser = [
                'use'              => '',
                'customProperties' => '',
                'implements'       => '',
                'customContent'    => '',
            ];
            if (file_exists($modelFile)) {
                $parser = (new ParseFile)->get($modelFile);
            }

            $ct = '';

            // ---------- 注释 ----------

            $ct .= "<?php" . "\n";
            $ct .= "" . "\n";
            $ct .= "namespace app\model;" . "\n";
            $ct .= "" . "\n";
            $ct .= 'use think\db\exception\DataNotFoundException;' . "\n";
            $ct .= 'use think\db\exception\DbException;' . "\n";
            $ct .= 'use think\db\exception\ModelNotFoundException;' . "\n";
            $ct .= $parser['use'];
            $ct .= "" . "\n";
            $ct .= "/**" . "\n";
            $ct .= " * @property int \$id" . "\n";
            $ct .= " * @property string \$created_at" . "\n";
            $ct .= " * @property string \$updated_at" . "\n";
            $ct .= " * @property int \$status" . "\n";
            $ct .= " *" . "\n";

            foreach ($cols as $col) {
                if (strpos($col['type'], 'INT') !== false) {
                    $ct .= " * @property int \${$col['col']} {$col['colCn']}" . "\n";
                } elseif (strpos($col['type'], 'DECIMAL') !== false) {
                    $ct .= " * @property float \${$col['col']} {$col['colCn']}" . "\n";
                } else {
                    $ct .= " * @property string \${$col['col']} {$col['colCn']}" . "\n";
                }
            }

            $ct .= " *" . "\n";
            foreach ($table['relations'] as $v) {
                $ct .= " * @property {$v['propertyType']} \${$v['property']}" . "\n";
            }

            if ($parser['customProperties']) {
                $ct .= $parser['customProperties'];
            }

            $ct .= " */" . "\n";

            $ct .= "class {$className} extends {$baseClassName} {$parser['implements']}" . "\n";
            $ct .= "{" . "\n";

            // ---------- tableName ----------

            $ct .= "    /**" . "\n";
            $ct .= "     * {@inheritdoc}" . "\n";
            $ct .= "     */" . "\n";
            $ct .= "    protected {$name} = '{$table['tableName']}';" . "\n";
            $ct .= "" . "\n";

            // ---------- schema ---------- 

            $ct .= "    protected  {$schema} = [" . "\n";
            $ct .= "        'id'           => 'int'," . "\n";
            $ct .= "        'created_at'   => 'datetime'," . "\n";
            $ct .= "        'updated_at'   => 'datetime'," . "\n";
            $ct .= "        'status'       => 'int'," . "\n";

            foreach ($cols as $col) {
                $ct .= "        '" . sprintf(
                        '%-13s',
                        $col['col'] . "'"
                    ) . " => '" . Str::lower($col['type']) . "', " . "\n";
            }
            $ct .= "    ];\n";
            $ct .= "\n";

            // ---------- relations ----------

            foreach ($table['relations'] as $v) {
                $ct .= "    public function {$v['get']}()" . "\n";
                $ct .= "    {" . "\n";
                if ($v['has'] == 'morphTo') {
                    $ct .= "        return \$this->{$v['has']}();" . "\n";
                } else {
                    $ct .= "        return \$this->{$v['has']}({$v['class']}::class, {$v['on']});" . "\n";
                }
                $ct .= "    }" . "\n";
                $ct .= "" . "\n";
            }

            $ct .= "    // ---------- Custom code below ----------";

            if (!empty($parser['customContent'])) {
                $ct .= $parser['customContent'];
            } else {
                $ct .= "" . "\n";
                $ct .= "}" . "\n";
                $ct .= "" . "\n";
            }

            file_put_contents($modelFile, $ct);
        }
    }

    protected function createARModel()
    {
        // 文件名
        $modelFile = root_path() . "/app/model/AR.php";

        if (file_exists($modelFile)) {
            return true;
        }

        $ct = '';

        $ct .= "<?php" . "\n";
        $ct .= "" . "\n";
        $ct .= "namespace app\model;" . "\n";
        $ct .= "" . "\n";
        $ct .= "class AR extends \\shisou\\tpgii\\lib\\AR" . "\n";
        $ct .= "{" . "\n";
        $ct .= "}" . "\n";

        file_put_contents($modelFile, $ct);
    }
}
